﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.Threading;
using System.Configuration;
using System.Diagnostics;
using NOS.Core;
using System.IO;
using NOS.Security;
using System.Web;

namespace NOS.Server
{
    //public delegate void delReceiveWebRequest(HttpListenerContext Context);

    public class NOSServer
    {

        #region . Variaveis .

        private string Port = "";

        private HttpListener httplis = null;

        #endregion

        #region . Funções Publicas .

        public void Start()
        {
            httplis = new HttpListener();
            Trace.WriteLine("\nhttpListener created...");

            try
            {
                Trace.Write("Getting the port number, ");
                Port = ":" + ConfigurationSettings.AppSettings.GetValues("Port").GetValue(0);
                Trace.WriteLine(" post is: "+Port);
            } catch { }

                       
            httplis.Prefixes.Add("http://*"+Port + "/");
            Trace.Write("Add http://*" + Port + "/ for listen\n");

            httplis.Start();

            NOSCore.LoadAssembliesCache();

            Trace.WriteLine("Service started\n");
            Trace.WriteLine("Listen in: "+Port);

            httplis.BeginGetContext(new AsyncCallback(WebRequestCallback), httplis);

            while (httplis.IsListening)
            {
                Thread.Sleep(50000);
            }           
        }

        #endregion

        #region . Funções Privadas .

        private void WebRequestCallback(IAsyncResult result)
        {
            HttpListenerContext context = httplis.EndGetContext(result);
            Trace.WriteLine("\nNew Call...");
            Trace.Write("Request: " + context.Request.UserHostAddress);
            Trace.WriteLine("  " + context.Request.UserAgent+"\n");

            httplis.BeginGetContext(new AsyncCallback(WebRequestCallback), httplis);

            string AbsolutePath = context.Request.Url.AbsolutePath;

            if (AbsolutePath.Split('/').GetValue(1).ToString() == "admin")
            {
                Trace.WriteLine("Administration Page");
                AdminRequest(context);
            }
            else
            {
                Trace.WriteLine("New process");
                Process(context);
            }
        }

        private void Process(HttpListenerContext Context)
        {
            NameValueCollection Parametros = new NameValueCollection();
            Trace.WriteLine("Calling NOS Core");
            NOSCore Nos = new NOSCore();

            if (Context.Request.HttpMethod == "POST")
            {
                Stream Input = Context.Request.InputStream;
                StreamReader Reader =  new StreamReader(Input, Context.Request.ContentEncoding);
                Parametros = HttpUtility.ParseQueryString(Reader.ReadToEnd(),Context.Request.ContentEncoding);
            }
            else
            {
                Parametros = Context.Request.QueryString;
            }

            WriteResponse(Context.Response, Nos.Process(Context.Request.Url.AbsolutePath,Parametros));
        }

        private void WriteResponse(HttpListenerResponse Response, string ResponsetoWrite)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(ResponsetoWrite);
            Response.ContentLength64 = buffer.Length;
            Stream output = Response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            output.Close();
        }

        private void AdminRequest(HttpListenerContext Context)
        {
            string Response = "";
            string Command = Context.Request.Url.AbsolutePath;

            if (Command == "/admin/")
            {
                Response = ADMINPAGE;
            }
            else if (Command == "/admin/reloadassemblies")
            {
                Response = ADMINRELOADWAIT; ;
            }
            else if (Command == "/admin/reloadassembliesexecute")
            {
                NOSCore.LoadAssembliesCache();
                Response = ADMINRELOADRESPONSE;
            }
            else if (Command == "/admin/registredservices")
            {
                Hashtable TmpHash = SafetyHashTable.GetShared();
                string TableServices = "";

                TableServices = "<Table border=\"1\" cellpadding=\"1\" cellspacing=\"1\">";
                TableServices += "<tr bgcolor=\"#DFF3B1\">";
                TableServices += "<td width=\"200px\">Service</td><td width=\"253px\">Assembly</td>";
                TableServices += "</tr>";                     
                foreach (object Item in TmpHash.Values)
                {
                    TableServices += "<tr>";
                    TableServices += "<td>" + ((DataHashTable)Item).ServiceName + "</td><td>" + ((DataHashTable)Item).AssemblyPath+"</td>";
                    TableServices += "</tr>";                     
                }
                TableServices += "</Table>";

                SafetyHashTable.ReleaseShared();

                Response = string.Format(ADMINREGISTREDSERVICES,TableServices);

            }
            else
            {
                Response = ERROR404;
            }

            WriteResponse(Context.Response,Response);
        }

        #endregion

        #region . Contantes .

        private const string ADMINPAGE = "<HTML><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><HEAD><TITLE>NOS - Administration</TITLE></HEAD><BODY style=\"font-family: Verdana\"><h3><U>NOS - Administration</U></h3><div id=\"Menu\"><div id =\"Menuitem\"><a href=\"reloadassemblies\">Reload Assemblies</a></div><div id =\"Menuitem\"><a href=\"registredservices\">Registred Services</a></div></div></BODY></HTML>";
        private const string ADMINRELOADRESPONSE = "<HTML><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><HEAD><TITLE>NOS - Administration</TITLE></HEAD><BODY style=\"font-family: Verdana\"><h3>Assemblies reload sucessfully</h3><br><a href=\"/admin/\">[ Home ]</a></BODY></HTML>";
        private const string ADMINRELOADWAIT = "<HTML><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><meta http-equiv=\"refresh\" content=\"0; url=reloadassembliesexecute\"><HEAD><TITLE>NOS - Administration</TITLE></HEAD><BODY style=\"font-family: Verdana\"><h3>Wait, reloading assemblies</h3><br>This operation can take some minutes</BODY></HTML>";
        private const string ADMINREGISTREDSERVICES = "<HTML><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><HEAD><TITLE>NOS - Administration</TITLE></HEAD><BODY style=\"font-family: Verdana\"><h3><U>Registred Services</U></h3><br>{0}<br><br><a href=\"/admin/\">[ Home ]</a></BODY></HTML>";
        private const string ERROR404 = "<HTML><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/><HEAD><TITLE>404 - Page not found</TITLE></HEAD><BODY style=\"font-family: Verdana\"><h3>Page not found</h3></BODY></HTML>";

        #endregion

    }
}
